from typing import Dict, Any, Optional, Set
import re
from pathlib import Path
from utils.logger import Logger
from utils.exceptions import ComplianceError
from middleware.redis_adapter import get_redis_adapter

# 初始化日志
logger = Logger.get_logger(agent_name="compliance_agent")


class ComplianceAgent:
    """合规检查Agent：敏感词过滤、内容合规校验"""

    def __init__(self):
        self.redis_client = get_redis_adapter()  # 使用Redis适配器，支持集群模式
        # 敏感词存储键（支持本地文件+Redis动态更新）
        self.sensitive_words_key = "compliance:sensitive_words"
        self.local_sensitive_file = Path(__file__).parent / "sensitive_words.txt"
        # 初始化敏感词库（本地文件加载+Redis补充）
        self.sensitive_words = self._load_sensitive_words()
        logger.info(f"合规检查Agent初始化成功，加载敏感词数: {len(self.sensitive_words)}")

    def _load_sensitive_words(self) -> Set[str]:
        """加载敏感词库（本地文件+Redis）"""
        sensitive_words = set()

        # 1. 加载本地敏感词文件（每行一个敏感词）
        try:
            if self.local_sensitive_file.exists():
                with open(self.local_sensitive_file, "r", encoding="utf-8") as f:
                    for line in f:
                        word = line.strip()
                        if word:
                            sensitive_words.add(word)
                logger.debug(f"从本地文件加载敏感词数: {len(sensitive_words)}")
        except Exception as e:
            logger.warning(f"本地敏感词文件加载失败: {str(e)}")

        # 2. 加载Redis中的敏感词（动态更新的词库）
        try:
            redis_words = self.redis_client.smembers(self.sensitive_words_key)
            if redis_words:
                redis_words = {word.decode("utf-8") for word in redis_words}
                sensitive_words.update(redis_words)
                logger.debug(f"从Redis加载敏感词数: {len(redis_words)}")
        except Exception as e:
            logger.warning(f"Redis敏感词加载失败: {str(e)}")

        return sensitive_words

    def add_sensitive_word(self, word: str) -> bool:
        """添加敏感词（同步到Redis，本地文件需手动维护）"""
        try:
            if not word or len(word.strip()) == 0:
                logger.warning("敏感词不能为空")
                return False
            word = word.strip()
            # 添加到Redis（Set去重）
            self.redis_client.sadd(self.sensitive_words_key, word)
            # 更新内存中的词库
            self.sensitive_words.add(word)
            logger.info(f"添加敏感词成功: {word}")
            return True
        except Exception as e:
            logger.error(f"添加敏感词失败: word={word}, error={str(e)}", exc_info=True)
            return False

    def remove_sensitive_word(self, word: str) -> bool:
        """删除敏感词（同步到Redis）"""
        try:
            word = word.strip()
            # 从Redis删除
            self.redis_client.srem(self.sensitive_words_key, word)
            # 从内存词库删除
            if word in self.sensitive_words:
                self.sensitive_words.remove(word)
            logger.info(f"删除敏感词成功: {word}")
            return True
        except Exception as e:
            logger.error(f"删除敏感词失败: word={word}, error={str(e)}", exc_info=True)
            return False

    def check_sensitive_words(self, text: str) -> Dict[str, Any]:
        """
        敏感词检测
        Returns:
            {"allowed": bool, "reason": str, "hit_words": List[str]}
        """
        if not text:
            return {"allowed": True, "reason": "文本为空", "hit_words": []}

        hit_words = set()
        # 敏感词匹配（支持全词匹配+部分匹配）
        for word in self.sensitive_words:
            if word in text:
                hit_words.add(word)

        if hit_words:
            reason = f"包含敏感词: {','.join(hit_words)}"
            logger.warning(f"敏感词检测不通过: text={text[:50]}, {reason}")
            return {"allowed": False, "reason": reason, "hit_words": list(hit_words)}

        logger.debug(f"敏感词检测通过: text={text[:50]}")
        return {"allowed": True, "reason": "无敏感词", "hit_words": []}

    def check_content_compliance(self, text: str) -> Dict[str, Any]:
        """
        内容合规综合校验（敏感词+违规模式）
        Returns:
            {"allowed": bool, "reason": str}
        """
        try:
            # 1. 敏感词检测
            sensitive_result = self.check_sensitive_words(text)
            if not sensitive_result["allowed"]:
                return sensitive_result

            # 2. 违规模式检测（如违法信息、广告推广等）
            illegal_patterns = [
                r"毒品|枪支|爆炸物|赌博|色情",  # 违法内容
                r"微信|QQ|手机号|电话|联系方式",  # 引流广告
                r"诈骗|钓鱼|刷单|洗钱",  # 违规行为
            ]
            for pattern in illegal_patterns:
                if re.search(pattern, text, re.IGNORECASE):
                    reason = f"包含违规内容（匹配模式：{pattern}）"
                    logger.warning(f"内容合规检测不通过: text={text[:50]}, {reason}")
                    return {"allowed": False, "reason": reason, "hit_words": []}

            logger.debug(f"内容合规检测通过: text={text[:50]}")
            return {"allowed": True, "reason": "内容合规", "hit_words": []}
        except Exception as e:
            logger.error(f"内容合规检测失败: text={text[:50]}, error={str(e)}", exc_info=True)
            return {"allowed": False, "reason": f"检测异常: {str(e)}", "hit_words": []}


# 单例实例
compliance_agent = ComplianceAgent()


# 简化外部调用函数
def check_compliance(text: str) -> Dict[str, Any]:
    """合规检查快捷函数（供orchestrator等模块直接调用）"""
    return compliance_agent.check_content_compliance(text)


# 本地敏感词文件示例（sensitive_words.txt）
# 若文件不存在，自动创建空文件
if not compliance_agent.local_sensitive_file.exists():
    with open(compliance_agent.local_sensitive_file, "w", encoding="utf-8") as f:
        f.write("敏感词1\n敏感词2\n敏感词3")  # 示例敏感词

# 测试入口
if __name__ == "__main__":
    test_logger = Logger.update_context(task_id="compliance_test", agent_name="compliance_agent")
    test_logger.info("开始测试合规检查Agent")

    # 测试用例
    test_texts = [
        "分布式多Agent系统的核心优势是什么？",  # 合规
        "出售毒品和枪支，联系QQ：123456",  # 不合规（敏感词+违法内容）
        "扫码添加微信领取红包，手机号：13800138000"  # 不合规（引流广告）
    ]

    for text in test_texts:
        result = check_compliance(text)
        test_logger.info(f"文本: {text[:30]} → 合规: {result['allowed']}, 原因: {result['reason']}")

    # 测试添加/删除敏感词
    compliance_agent.add_sensitive_word("测试敏感词")
    result = check_compliance("这个文本包含测试敏感词")
    test_logger.info(f"添加敏感词后检测: {result}")

    compliance_agent.remove_sensitive_word("测试敏感词")
    result = check_compliance("这个文本包含测试敏感词")
    test_logger.info(f"删除敏感词后检测: {result}")

    test_logger.success("合规检查Agent测试完成")